#pragma once
#include <memory>
#include <atomic>
#include <map>
#include <future>

#include "jse_env.h"
#include "quickjspp.hpp"


struct javascript_env_pack {
    std::shared_ptr<javascript_environment> env;
    std::future<bool> f;

    javascript_env_pack(const std::shared_ptr<javascript_environment>& env, std::future<bool>& f)
    :env(env), f(std::move(f))
    {}

    bool close()
    {
        if(!env)
            return true;
        env->stop();
        if(!f.valid())
            return true;
        return f.get();
    }
};

/**
 * @brief 管理器类
 * 
 */
class javascript_manager
{
using js_env_pack_ptr = std::shared_ptr<javascript_env_pack>;

private:
    std::atomic_int count_ = 0;
    static javascript_manager manager_;
    std::map<int, js_env_pack_ptr> envs_;

private:
    javascript_manager();

    bool thread_entry(std::shared_ptr<javascript_environment> env);

public:
    static javascript_manager &get();

    /**
     * @brief Create a env object
     * 
     * @return int the global env index
     */
    int create_env();

    /**
     * @brief 停止env
     * 
     */
    bool close_env(int id);

    /**
     * @brief 关闭所有js环境
     * 
     */
    void close_all();

    /**
     * @brief 执行js代码
     * 
     * @param id 
     * @param javascript 
     * @return qjs::Value 
     */
    qjs::Value eval_javascript_string(int id, const std::string& javascript);

    qjs::Value eval_javascript_file(int id, const std::string& filepath);
};